-- weak table

a = {}
mt = {__mode = "k"} 	-- weak reference
setmetatable(a, mt)
key = {}
a[key] = 1
key = {}
a[key] = 2

collectgarbage()
for k, v in pairs(a) do print(v) end

-- memory function
local results = {}
setmetatable(results, {__mode = "v"})

function mem_loadstring (s)
	local res = results[s]

	if res == nil then
		res = assert(load(s))
		results[s] = res
	end

	return res
end

function createRGB (r, g, b)
	local key = string.format("%d-%d-%d", r, g, b)
	local color = results[key]

	if color == nil then
		color = {red = r, green = g, blue = b}
		results[key] = color
	end

	return color
end

-- a table with default value
-- solution 1
local defaults = {}
setmetatable(defaults, {__mode = "k"})
local mt = {__index = function (t) return defaults[t] end}
function setDefault (t, d)
	defaults[t] = d
	setmetatable(t, mt)
end
-- solution 2
local metas = {}
setmetatable(metas, {__mode = "v"})
function setDefault1 (t, d)
	local mt = metas[d]
	if mt == nil then
		mt = {__index = function () return d end}
		metas[d] = d
	end
	setmetatable(t, mt)
end

-- ephemeron table (key is weak reference, value is strong reference)
-- for ephemeron table, the reference to key of its value is not a strong reference
do
	local mem = {}
	setmetatable(mem, {__mode = "k"})
	function factory (o)
		local res = mem[o]
		if not res then
			res = (function () return o end)
			mem[o] = res
		end
		return res
	end
end

-- finalizer
o = {x = "hi"}
setmetatable(o, {__gc = function (o) print(o.x) end})
o = nil

collectgarbage() 	-- hi

